package eyer.jvm;

import java.lang.management.GarbageCollectorMXBean;
import java.lang.management.ManagementFactory;
import java.util.ListIterator;

public class JVMGC implements JVMGCMBean {
    private static JVMGC instance = new JVMGC();
    private GarbageCollectorMXBean fullGC;
    private GarbageCollectorMXBean youngGC;

    public static JVMGC getInstance() {
        return instance;
    }

    private long lastYoungGCCollectionCount = -1L;
    private long lastYoungGCCollectionTime = -1L;
    private long lastFullGCCollectionCount = -1L;
    private long lastFullGCCollectionTime = -1L;

    private JVMGC() {
        for (ListIterator<GarbageCollectorMXBean> iter = ManagementFactory.getGarbageCollectorMXBeans().listIterator(); iter
                .hasNext();) {
            GarbageCollectorMXBean item = (GarbageCollectorMXBean) iter.next();
            if (("ConcurrentMarkSweep".equals(item.getName()))
                    || ("MarkSweepCompact".equals(item.getName()))
                    || ("PS MarkSweep".equals(item.getName()))
                    || ("G1 Old Generation".equals(item.getName()))
                    || ("Garbage collection optimized for short pausetimes Old Collector".equals(item.getName()))
                    || ("Garbage collection optimized for throughput Old Collector".equals(item.getName()))
                    || ("Garbage collection optimized for deterministic pausetimes Old Collector"
                            .equals(item.getName()))) {
                this.fullGC = item;
            } else if (("ParNew".equals(item.getName()))
                    || ("Copy".equals(item.getName()))
                    || ("PS Scavenge".equals(item.getName()))
                    || ("G1 Young Generation".equals(item.getName()))
                    || ("Garbage collection optimized for short pausetimes Young Collector".equals(item.getName()))
                    || ("Garbage collection optimized for throughput Young Collector".equals(item.getName()))
                    || ("Garbage collection optimized for deterministic pausetimes Young Collector".equals(item
                            .getName()))) {
                this.youngGC = item;
            }
        }
    }

    public long getYoungGCCollectionCount() {
        if (this.youngGC == null) {
            return 0L;
        }
        return this.youngGC.getCollectionCount();
    }

    public long getYoungGCCollectionTime() {
        if (this.youngGC == null) {
            return 0L;
        }
        return this.youngGC.getCollectionTime();
    }

    public long getFullGCCollectionCount() {
        if (this.fullGC == null) {
            return 0L;
        }
        return this.fullGC.getCollectionCount();
    }

    public long getFullGCCollectionTime() {
        if (this.fullGC == null) {
            return 0L;
        }
        return this.fullGC.getCollectionTime();
    }

    public long getSpanYoungGCCollectionCount() {
        long current = getYoungGCCollectionCount();
        if (this.lastYoungGCCollectionCount == -1L) {
            this.lastYoungGCCollectionCount = current;
            return 0L;
        }
        long reslut = current - this.lastYoungGCCollectionCount;
        this.lastYoungGCCollectionCount = current;
        return reslut;
    }

    public long getSpanYoungGCCollectionTime() {
        long current = getYoungGCCollectionTime();
        if (this.lastYoungGCCollectionTime == -1L) {
            this.lastYoungGCCollectionTime = current;
            return 0L;
        }
        long reslut = current - this.lastYoungGCCollectionTime;
        this.lastYoungGCCollectionTime = current;
        return reslut;
    }

    public long getSpanFullGCCollectionCount() {
        long current = getFullGCCollectionCount();
        if (this.lastFullGCCollectionCount == -1L) {
            this.lastFullGCCollectionCount = current;
            return 0L;
        }
        long reslut = current - this.lastFullGCCollectionCount;
        this.lastFullGCCollectionCount = current;
        return reslut;
    }

    public long getSpanFullGCCollectionTime() {
        long current = getFullGCCollectionTime();
        if (this.lastFullGCCollectionTime == -1L) {
            this.lastFullGCCollectionTime = current;
            return 0L;
        }
        long reslut = current - this.lastFullGCCollectionTime;
        this.lastFullGCCollectionTime = current;
        return reslut;
    }
}
